/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nus.util;

import com.nus.dataaccess.dao.base.BaseEntity;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtils;

/**
 *
 * @author robin.foe
 */
public class BeanUtil {
    
    @SuppressWarnings({ "rawtypes" })
	public static void copyProperties(Object destinationBean,Object sourceBean,String... excludedPropertyName)throws Exception{
		if(excludedPropertyName == null || excludedPropertyName.length == 0)
			PropertyUtils.copyProperties(destinationBean, sourceBean);
		else{
			Map map = BeanUtil.describe(destinationBean, sourceBean);
			for(String exclude : excludedPropertyName)
				map.remove(exclude);
			
			PropertyUtils.copyProperties(destinationBean,map);
		}
	}
	
	
	public static List<?> cloneArrayProperties(ArrayList<?> cloneList, Class<?> klass){
		List<Object> list = new ArrayList<Object>();
		
		for(int i = 0; i < cloneList.size();i++){
			try {
				Object obj;
				obj = klass.newInstance();
				Object _ori = cloneList.get(i);
				BeanUtil.copyProperties(obj, _ori);
				list.add(obj);
			} catch (Exception e) {e.printStackTrace();}
			
		}
		
		return list;
	}
	
	@SuppressWarnings("rawtypes")
	public static List<Class<?>> getEntityGenericClasses(Class entityClass){
		List<Class<?>>genericClasses = new ArrayList<Class<?>>();
		genericClasses.add(entityClass);
	    while(true){
	    	if(genericClasses.get(0).getSuperclass().equals(BaseEntity.class))
	    		break;
	    	else
	    		genericClasses.add(0,genericClasses.get(0).getSuperclass());
	    }
	    
	    return genericClasses;
	}
   
	public static Map<String,Object> describe(Object destinationBean,Object sourceBean, String... excludedPropertyName)throws Exception{
		Map<String,Object> map = null;
		/*
		 	extremely unsecured to be used with hibernate, always give lazy init exception
		 * try{
			map = PropertyUtils.describe(sourceBean);
		}catch(Exception e){IGNORED}*/
		
		// mostlikely error happen., then we have to mannually dig
		if(map == null){
			map = new HashMap<String,Object>();
			List<Field> fields = new ArrayList<Field>();
			List<String> excludedProperties = Arrays.asList(excludedPropertyName);
			
			
			@SuppressWarnings("rawtypes")
			Class currentKlass = destinationBean.getClass();
			while(true){
				fields.addAll(Arrays.asList(currentKlass.getDeclaredFields()));
				currentKlass = currentKlass.getSuperclass();
				if(currentKlass == null || "java.lang.Object".equals(currentKlass.getName()))
					break;
			}
			
			for(Field field : fields){
				try{
					if(excludedProperties.contains(field.getName()))
						continue;
					
					map.put(field.getName(), PropertyUtils.getProperty(sourceBean, field.getName()));
					/*field.setAccessible(true);
					map.put(field.getName(), field.get(sourceBean));*/
				}catch(Exception e){/*IGNORED*/}
			}
		}
		
		return map;
	}
    
}
